home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 24
/
Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso
/
Aminet
/
util
/
arc
/
PPCTarWOS.lha
/
PPCDeTar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-02-18
|
11KB
|
521 lines
/*
** $VER: DeTar.c 1.5 (15.2.98)
**
** DeTar main module
**
** written in 1995-98 by Andreas R. Kleinert, based on code by Steve Sampson
** Public Domain. (See DeTar.doc)
** Modified by Steffen P. Häuser to use WarpOS instead of - ELF sucks -
** ppc.library
*/
/* ------------------------------------------------------------------------------ */
/*
* detar.c
*
* Version 1.1
*
* Fixed bug in convert() wich produced errors on files without
* a slash '/' in them.
*
* Unix Tape Archive (TAR) Extractor for MSDOS
*
* Public Domain January 1988, Steve Sampson
* Based on the public domain TAR program by John Gilmore
*
* Compiled with ECO-C88 V3.21
*
*/
/* Includes */
#define __USE_SYSBASE
#include <exec/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include "detar.h"
/* Defines */
#define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
/* Globals */
FILE *fdi,
*fdo;
union record *head; /* the archive file header */
struct stat hstat; /* the decoded stat info */
struct {
long year;
long month;
long day;
long hour;
long min;
long sec;
} tm;
long ugswidth = 11;
long dir_only = 0;
char tempname[256];
char version [] = "\0$VER: detar 1.5 (15.2.98)";
/* Forward References, Prototypes */
void dir_tar(void);
void de_tar(void);
void decode_header(union record *header, struct stat *st, long *stdp);
void demode(unsigned mode, char *string);
long from_oct(long digs, char *where);
/* Main Program */
void main(long argc, char **argv)
{
char *p;
long retval = 0;
long add = FALSE, valid = FALSE;
if(!argc) exit(20);
/* The operator can ask for directory only or de-tar only. */
argv++;
if(argc == 3 && **argv == 'd')
{
dir_only++;
argc--;
argv++;
}
if (argc != 2)
{
fprintf(stderr, &version[7]);
fprintf(stderr, "\nWarpOS PPC Port by Steffen Haeuser in 1998. Public Domain."
"\nAmiga Port by Andreas R. Kleinert in 1995-98. Public Domain."
"\nPublic Domain January 1988, Steve Sampson"
"\nBased on the public domain TAR program by John Gilmore");
fprintf(stderr, "\nUsage: detar [d] filename[.tar]");
fprintf(stderr, "\nWhere d means 'list content only'\n");
exit(1);
}
for (p = *argv; *p; p++) *p = (char)toupper(*p);
/* parse the many possibilities, this stuff not needed with MSC */
if ((p = strrchr(*argv, '.')) == (char *)NULL) { add = valid = TRUE; }
else if (strcmp(p, ".TAR") == NULL) { strcpy(tempname, *argv); valid = TRUE; }
else if (*(p+1) == '/' || *(p+1) == '\\') { add = valid = TRUE; valid = TRUE; }
if(valid)
{
if(add)
{
strcpy(tempname, *argv);
strcat(tempname, ".TAR");
}
fdi = fopen(tempname, "rb");
if(fdi)
{
setvbuf(fdi, NULL, _IOFBF, 8192);
head = (union record *)malloc(512);
if(head)
{
if (dir_only) dir_tar();
else de_tar();
free(head);
}else
{
fprintf(stderr, "Not enough memory !\n");
retval = 20;
}
fclose(fdi);
}else
{
fprintf(stderr, "Tar file '%s' not found\n", tempname);
retval = 20;
}
}else
{
fprintf(stderr, "File '%s' not a TAR archive\n", *argv);
retval = 20;
}
exit(retval);
}
/*
* Produce a directory of the files contained on the TAR
*/
void dir_tar(void)
{
char modes[11], *timestamp;
char uform[11], gform[11];
char *user, *group, size[24];
long n, pad, header_std;
time_t timeval;
for (;;)
{
if ((n = fread((char *)head, 1, 512, fdi)) == EOF)
{
return;
}
decode_header(head, &hstat, &header_std);
/* File type and modes */
modes[0] = '?';
switch (head->header.linkflag)
{
case LF_NORMAL:
case LF_OLDNORMAL:
case LF_LINK:
{
modes[0] = '-';
if ('/' == head->header.name[strlen(head->header.name)-1])
modes[0] = 'd';
break;
}
case LF_DIR:
{
modes[0] = 'd';
break;
}
case LF_SYMLINK:
{
modes[0] = 'l';
break;
}
case LF_BLK:
{
modes[0] = 'b';
break;
}
case LF_CHR:
{
modes[0] = 'c';
break;
}
case LF_FIFO:
{
modes[0] = 'f';
break;
}
case LF_CONTIG:
{
modes[0] = '=';
break;
}
}
demode(hstat.st_mode, modes+1);
/* Timestamp */
timeval = hstat.st_mtime;
timestamp = ctime(&timeval);
timestamp[16] = '\0';
timestamp[24] = '\0';
/* User and group names */
if (*head->header.uname && header_std)
{
user = head->header.uname;
}else
{
user = uform;
sprintf(uform, "%ld", (long)hstat.st_uid);
}
if (*head->header.gname && header_std)
{
group = head->header.gname;
}else
{
group = gform;
sprintf(gform, "%ld", (long)hstat.st_gid);
}
/* Format the file size or major/minor device numbers */
switch (head->header.linkflag)
{
case LF_CHR:
case LF_BLK:
{
sprintf(size, "%ld, %ld",
(long)from_oct(8, head->header.devmajor),
(long)from_oct(8, head->header.devminor));
break;
}
default:
{
sprintf(size, "%ld", hstat.st_size);
break;
}
}
/* Figure out padding and print the whole line. */
pad = strlen(user) + strlen(group) + strlen(size) + 1;
if (pad > ugswidth) ugswidth = pad;
printf("%s %s/%s %*s%s %s %s %.*s",
modes,
user,
group,
ugswidth - pad,
"",
size,
timestamp+4, timestamp+20,
sizeof(head->header.name),
head->header.name);
switch (head->header.linkflag)
{
case LF_SYMLINK:
{
printf(" -> %s\n", head->header.linkname);
break;
}
case LF_LINK:
{
printf(" link to %s\n", head->header.linkname);
break;
}
default:
{
printf(" unknown file type '%c'\n", head->header.linkflag);
break;
}
case LF_OLDNORMAL:
case LF_NORMAL:
case LF_CHR:
case LF_BLK:
case LF_DIR:
case LF_FIFO:
case LF_CONTIG:
{
putc('\n', stdout);
break;
}
}
/* Seek to next file */
fseek(fdi, hstat.st_size, SEEK_CUR);
/* File starts on 512 byte boundary */
fseek(fdi, 512L - (hstat.st_size % 512L), SEEK_CUR);
}
}
/*
* Extract the files from the TAR archive
*
*/
void de_tar(void)
{
ULONG size, filesize;
long header_std, c, len;
char *workfile;
for (;!feof(fdi);)
{
if ( fread((char *)head, 1, 512, fdi) == (unsigned int) EOF) break;
decode_header(head, &hstat, &header_std);
workfile = head->header.name;
size = filesize = hstat.st_size;
len = strlen(workfile);
if(len > 0)
{
if( (workfile[len-1] == '/')
|| (workfile[len-1] == ':') )
{
BPTR lock;
printf("Creating: %s ...", workfile);
workfile[len-1] = (char) 0;
lock = CreateDir(workfile);
if(lock)
{
printf(" OK\n");
UnLock(lock);
}else printf(" Failed\n");
fseek(fdi, filesize, SEEK_CUR);
continue;
}
printf("Extracting: %s\n", workfile);
fdo = fopen(workfile, "wb");
if(fdo)
{
setvbuf(fdo, NULL, _IOFBF, 8192);
while ((c = getc(fdi)) != EOF)